#ifndef PW_PBL_META_VHSTR_HPP
#define PW_PBL_META_VHSTR_HPP

#include "VHArray.hpp"
#include "String.hpp"
#include <string_view>

namespace pw_pbl::Meta
{
	template <typename CHAR = char, size_t... N>
	requires requires { std::char_traits<std::remove_const_t<CHAR>>{}; } && (sizeof...(N) <= 1)
	struct VHStr;

	template <typename CHAR>
	struct VHStr<CHAR> : public VHArray<CHAR>
	{
		inline auto *cstr() const noexcept { return this->begin(); }
		template <typename... T>
		inline operator std::basic_string_view<CHAR, T...>() const noexcept { return {this->begin(), this->size()}; }

		template <std::ranges::sized_range T> requires std::convertible_to<std::ranges::range_value_t<T>, const CHAR>
		inline size_t write(T &&view, size_t maxBytesSize) noexcept
		{
			if (maxBytesSize <= sizeof(CHAR))
				return 0;
			auto sz = VHArray<CHAR>::write(std::forward<T>(view), maxBytesSize - sizeof(CHAR));
			if (sz == 0)
				return sz;
			*(CHAR *)((char *)this->header().data() + sz) = CHAR{};
			return sz + sizeof(CHAR);
		}

	protected:
		VHStr() = default;
		VHStr(VHStr &&) = default;
		VHStr(const VHStr &) = default;
	};

	template <typename CHAR, size_t N>
	struct VHStr<CHAR, N> : public VHStr<CHAR>
	{
		using char_type = CHAR;
		static constexpr size_t ESize = N - 1;

		_vhdata::Header<char_type, ESize> header;
		char_type _data[ESize];

		consteval VHStr(const char_type (&_data)[N]) noexcept { std::copy_n(_data, ESize, this->_data); }
		consteval VHStr(const Str<CHAR, N> &_data) noexcept : VHStr(_data.data()) {}

		bool operator==(const VHStr &) const = default;
		template <typename NC, size_t NN>
		constexpr bool operator==(const VHStr<NC, NN> &) const { return false; }
	};
	template <typename CHAR, size_t N>
	VHStr(const CHAR (&)[N]) -> VHStr<CHAR, N>;
	template <typename CHAR, size_t N>
	VHStr(const Str<CHAR, N> &) -> VHStr<CHAR, N>;

	template <typename CHAR = const char>
	struct VHStrPtr
	{
		static constexpr auto EIsConst = std::is_const_v<CHAR>;
		using TStr = std::conditional_t<EIsConst, const VHStr<std::remove_const_t<CHAR>>, VHStr<CHAR>>;

		union
		{
			TStr *pStr;
			std::conditional_t<EIsConst, const void, void> *pVoid;
		};

		constexpr VHStrPtr(TStr &raw) noexcept : pStr{&raw} {}

		constexpr TStr &operator*() const noexcept { return *pStr; }
		constexpr TStr *operator->() const noexcept { return pStr; }
		explicit constexpr operator bool() const noexcept { return pStr != nullptr; }

		template <typename TRAITS>
		constexpr operator std::basic_string_view<std::remove_const_t<CHAR>, TRAITS>() const noexcept { return {pStr->begin(), pStr->size()}; }

		/// 从任意指针构造vl指针，注意必须确认指针指向的布局为VLArray（vl头+纯数组）
		template <typename T> requires(alignof(T) == alignof(CHAR))
		explicit constexpr VHStrPtr(T *p) noexcept : pVoid(p) {}

		constexpr size_t size() const noexcept { return pStr->size(); }
		constexpr auto *begin() const noexcept { return pStr->begin(); }
		constexpr auto *end() const noexcept { return begin() + size(); }
		constexpr auto *data() const noexcept { return begin(); }
	};
	template <typename CHAR>
	VHStrPtr(VHStr<CHAR> &) -> VHStrPtr<CHAR>;
	template <typename CHAR>
	VHStrPtr(const VHStr<CHAR> &) -> VHStrPtr<const CHAR>;

	inline namespace literals
	{
		template <VHStr STR>
		constexpr auto &operator""_vhstr() { return STR; }

		template <VHStr STR>
		constexpr auto &MetaVHStr = STR;
	} // namespace literals

} // namespace pw_pbl::Meta

#endif // PW_PBL_META_VHSTR_HPP
